package edu.tongji.engine.service;

import java.util.List;
import java.util.Set;

import edu.tongji.engine.common.Log;
import edu.tongji.engine.db.dao.DAOFactory;
import edu.tongji.engine.db.dao.ITokenDao;
import edu.tongji.engine.def.ActivityNode;
import edu.tongji.engine.def.Node;
import edu.tongji.engine.def.Transition;
import edu.tongji.engine.exe.ProcessInstance;
import edu.tongji.engine.exe.Token;
import edu.tongji.engine.taskmgr.TaskMgrService;

public class TokenService {
	
	private ITokenDao tokenDao;
	//private TaskMgrService taskService;
	//private Token token;
	
	public TokenService(){
		tokenDao = DAOFactory.createTokenDao();
		//taskService = new TaskMgrService();
		//token = new Token();
	}
	
	public void next(Token token){
		if(token==null){
			 //throw new IllegalArgumentException("can't get token");
			 System.out.println("can't get token");
		}
		Node node = token.getNode();
		if(node==null){
			System.out.println("can't get token node");
		}else{
			System.out.println(node.getName()+" ..."+token.getNode().getType_name());
		}
		String state = token.getState().trim();
		Transition trans = node.getLeavingTransition();
		try{
			if (node.getType_name().equals("StartNode") ) {
				
				if ( state.equals("arriving") ){
					node.EnterEnvent(token);
					token.setState("on_node");
				}else if ( state.equals("on_node") ){
					node.LeaveEvent(token);
					token.setState("leaving");
				}else if( state.equals("leaving") ){
					token.setNode(trans.getTo_node());
					token.setState("arriving");
				}
				
				
			}else if (node.getType_name().equals("ActivityNode")){
				//when come to a node first, need to create a task
				if ( state.equals("arriving") ){
					if (node.getEnterEventHandler()!=null){
						//taskService.createTask((ActivityNode)node, token);
						node.EnterEnvent(token);
					}
					
					token.setState("on_node");
				}else if ( state.equals("on_node") ){
				
						if (node.getLeaveEventHandler()!=null){
							//taskService.createTask((ActivityNode)node, token);
							node.LeaveEvent(token);
						}
					
					token.setState("leaving");
					
				}else if( state.equals("leaving") ){
					token.setNode(trans.getTo_node());
					token.setState("arriving");
				}
			}else if(node.getType_name().equals("EndNode")){
				if ( state.equals("arriving") ){
					node.EnterEnvent(token);
					token.setState("on_node");
				}else if ( state.equals("on_node") ){
					node.LeaveEvent(token);
					token.setState("leaving");
					
				}else if (state.equals("leaving") ){
					System.out.println("process has finished!");
				}
			}else if (node.getType_name().equals("ForkNode")){
				
				node.EnterEnvent(token);
				//create child tokens
				this.createChildTokens(token);
				
				
			}else if (node.getType_name().equals("JoinNode")){
				this.mergeChildTokens(token);
			}
		}
		catch(Exception e){
			System.out.println(e.toString());
		}
		finally{
			tokenDao.saveToken(token);
			System.out.println("save token");
		}
	}
	
	public boolean createChildTokens(Token token){
		Set<Transition> trans = token.getNode().getLeavingTransitions();
		//Transition trans1 = token.getNode().getArrivingTransition();
		//Transition trans2 = token.getNode().getLeavingTransition();
		//System.out.println("  arriving "+trans1.getName()+" leaving "+trans2.getName());
		try{
			ProcessInstance pi = token.getPi();
			for ( Transition tran : trans ){
				Token newToken = new Token();
				newToken.setContext(token.getContext());
				newToken.setPi(pi);
				newToken.setState("arriving");
				newToken.setNode(tran.getTo_node());
				tokenDao.saveToken(newToken);
				//delete parent token
				tokenDao.deleteToken(token);
			}
		return true;
		}catch(Exception e){
			e.printStackTrace();
			Log.getLoger().loger.error(" create childTokens Fail! ", e);
			return false;
		}
	}
	
	public boolean mergeChildTokens(Token token){
		try{
			Node node = token.getNode();
			List<Token> tokens = this.getNodeTokens(token);
			if ( tokens.size() == node.getArrivingTransitions().size() ){
				//if all child tokens come to Join Node, Join all child Tokens
				Token newToken = new Token();
				Transition tran = node.getLeavingTransition();
				newToken.setContext(token.getContext());
				newToken.setPi(token.getPi());
				newToken.setNode(tran.getTo_node());
				System.out.println(tran.getTo_node().getName());
				newToken.setState("arriving");
				
				for ( Token child : tokens ){
					tokenDao.deleteToken(child);
				}
				
				tokenDao.saveToken(newToken);
			}
			return true;
		}catch(Exception e){
			e.printStackTrace();
			Log.getLoger().loger.error(" create childTokens Fail! ", e);
			return false;
		}
	}
	
	public Token getToken(String processInstanceName){
		return tokenDao.getProcessToken(processInstanceName);
	}
	
	public Token getTokenById(Long id){
		return tokenDao.getTokenById(id);
	}
	
	public List<Token> getNodeTokens(Token token){
		
		return tokenDao.getNodeTokens(token);
		
	}
}
